﻿using System;

namespace N2.ComponentModel
{
	/// <summary>
	/// Encapsulates a generic reference-type class property member,
	/// hiding an implementation of a default value resolution.
	/// </summary>
	/// <typeparam name="PropertyType"></typeparam>
	/// <typeparam name="ContainerItemType"></typeparam>
	public class GenericPropertyHolder<PropertyType, ContainerItemType>
		where PropertyType: class
	{
		#region Fields
		
		readonly ContainerItemType m_item;
		readonly Func<ContainerItemType, PropertyType> m_resolver;
		
		#endregion Fields
		
		#region ctor
		
		/// <summary>
		/// Constructs a property holder.
		/// To called as early as possible.
		/// </summary>
		/// <param name="item">An instance of a property owner</param>
		/// <param name="resolver">Delegate that resolves a default property value</param>
		public GenericPropertyHolder(
			ContainerItemType item,
			Func<ContainerItemType, PropertyType> resolver)
		{
			this.m_item = item;
			this.m_resolver = resolver;
		}
		
		#endregion ctor
		
		#region Properties
		
		PropertyType m_value;
		public PropertyType Value {
			get {
				return this.m_value
					?? (this.m_value = this.m_resolver(this.m_item));
			}
			set { this.m_value = value; }
		}
		
		#endregion Properties
	}

//TODO decide whether to keep it, not sure about 'new' design
	public class ReadOnlyPropertyHolder<PropertyType, ContainerItemType>
		: GenericPropertyHolder<PropertyType, ContainerItemType>
		where PropertyType: class
	{
		#region ctor

		public ReadOnlyPropertyHolder(
			ContainerItemType item,
			Func<ContainerItemType, PropertyType> resolver)
			:base(item, resolver) {}
		
		#endregion ctor

		#region Properties

		public new PropertyType Value {
			get { return base.Value; }
		}

		#endregion Properties
	}
}
